#!/usr/bin/evn python
# -*- encoding: utf-8 -*-

import MySQLdb
import os
import datetime
import json
import sys


class PlanCronScript:
    def __init__(self, host='', userName='', passWord='',charset='utf8'):
        self.host = host
        self.userName = userName
        self.passWord = passWord
        self.charset = charset
        self.dbconn = None
        self.cursor = None
        self.scriptNum = None
        self.QUERY_PLAN_CROND_STR = """
             SELECT 
                t.type,
                p.pid, 
                t.filepath, 
                p.args,
                p.company,
                t.handle
            FROM
                information.plan p,
                information.task t
            WHERE
                t.tid = p.tid 
                AND p.status = 0
                AND p.executetime = '%s'
                AND t.handle= %s
        """
        self.UPDATE_PLAN_INVALID_STR = """update information.plan set info = "%s", status = %s where pid = %s"""

    def openDBConnect(self):
        self.dbconn = MySQLdb.connect(self.host, self.userName, self.passWord, charset=self.charset)

    def closeDBConnect(self):
        if self.dbconn:
            self.dbconn.close()
            self.dbconn = None

    def getDBCursor(self):
        if not self.dbconn:
            self.openDBConnect()
        self.cursor = self.dbconn.cursor()

    def commit(self):
        self.dbconn and self.dbconn.commit()

    def rollback(self):
        self.dbconn and self.dbconn.rollback()

    def handle(self, currentTime, handle):

        self.cursor.execute(self.QUERY_PLAN_CROND_STR % (currentTime, handle))
        _plans = self.cursor.fetchall()

        for i, v in enumerate(_plans):
            type = int(v[0])
            pid = int(v[1])
            filepath = v[2]
            args = v[3]
            company = v[4]

            executeStr = u"%s %s %s %s %s &" % ((type == 0 and "python" or "sh"), filepath, pid, args, company)
            os.system(executeStr)

            if i + 1 > self.scriptNum:
                self.cursor.execute(self.UPDATE_PLAN_INVALID_STR % (u"同一时段超载自动取消,请稍后再试", 3, pid))

            self.commit()

    # 零点时更新超出配置容量的为失败
    def UpdateFailed(self):
        sqls = """ SELECT pid FROM information.plan WHERE status=0 ORDER BY pid"""
        updataSQL = """UPDATE information.plan  SET status = 3 WHERE pid = %s"""

        self.cursor.execute(sqls)
        count = self.cursor.fetchall()

        if count > self.scriptNum:
            for i, v in enumerate(count):
                if i + 1 > self.scriptNum:
                    self.cursor.execute(updataSQL % v[0])
                    self.commit()

    def main(self,handle, scriptNum):

        self.scriptNum = scriptNum

        currentTime = datetime.datetime.now().strftime('%y%m%d%H%M')
        self.getDBCursor()

        if currentTime[-4:] == "0000":
            self.UpdateFailed()

        self.handle(currentTime,handle)

        self.closeDBConnect()

        sys.exit(0)

if __name__ == "__main__":
    """
    系统级别
    当前文件配置在 /var/spool/cron/root 下root 文件(Linux)
    /sbin/service crond start    //启动服务
　　/sbin/service crond stop     //关闭服务
　　/sbin/service crond restart  //重启服务
　　/sbin/service crond reload   //重新载入配置
　　/sbin/service crond status   //查看服务状态
    * * * * * python /home/fanglin/cronbin/crond_plan_timing_handle.py 0 10
    本脚本命令为:
    python /home/fanglin/cronbin/crond_plan_timing_handle.py <0读1写> <执行阈值>
    python /home/fanglin/cronbin/crond_plan_timing_handle.py 0 10
    
    定时任务:控制每分钟需要执行的脚本
    1.当时间为每日零点零分时 :会进行未执行脚本数量检查,只保留配置容量,超出则更新状态为失败
    2.每分钟检查数据库中状态为0的脚本,当时间符合,进行执行,当该时间(分钟)将要执行的数量超出配置容量,超出部分状态更新为失败,并提示,同一时段超载自动取消,请稍后再试
    执行命令
        <python/sh> <filepath:脚本路径> <pid:任务主键> <args:自定义脚本参数> <company:公司>
        sh /home/fanglin/cronbin/plan_achievement_decoration_collecter.py 667 2015/08/02-2018/10/03 0 0
        python /home/fanglin/cronbin/plan_achievement_decoration_collecter.py 668 2015/08/02-2018/10/03 0 0
    """
    modernFilePath = os.path.realpath(__file__)
    configPath = "%s/%s" % (os.path.dirname(modernFilePath), "config.json")

    config = json.load(open(configPath))
    dbconf = config.get("database")

    handle = sys.argv[1]
    scriptNum = sys.argv[2]

    plans = PlanCronScript(dbconf.get("host"), dbconf.get("username"), dbconf.get("password"))
    plans.main(int(handle), int(scriptNum))
